﻿using System.Collections.Generic;
using System.Linq;
using System.Windows;
using WPFSchematics.Definition.Entities.Collection;
using WPFSchematics.Definition.Shapes;
//using WPFSchematics.Graphics.Helpers;

namespace WPFSchematics.Graphics.Ghosts
{
    /// <summary>
    /// 幻影剪贴板。用于图形的拷贝、剪切、粘贴操作。
    /// </summary>
    public static class GhostClipboard
    {
        /// <summary>
        /// 是否有幻影。即粘贴操作是否可用。
        /// </summary>
        public static bool IsDirty
        {
            get { return CopiedGhosts.Count > 0; }
        }

        /// <summary>
        /// 新图元设备集合。
        /// </summary>
        public static List<IShapeFeature> NewFeatures { get; private set; }

        /// <summary>
        /// 被复制的幻影集合。
        /// </summary>
        private static readonly List<GhostObject> CopiedGhosts = new List<GhostObject>();

        /// <summary>
        /// 静态构造。
        /// </summary>
        static GhostClipboard()
        {
            NewFeatures = new List<IShapeFeature>();
        }

        /// <summary>
        /// 复制。
        /// </summary>
        /// <param name="features">图元集合。</param>
        public static void Copy(List<IShapeFeature> features)
        {
            if (features.Count > 0)
            {
                CopiedGhosts.Clear();
                foreach (var featue in features)
                {
                    CopiedGhosts.Add(((IGhostHost)featue).Ghost);
                }
            }
        }

        /// <summary>
        /// 剪切。
        /// </summary>
        /// <param name="features">图元集合。</param>
        public static void Cut(List<IShapeFeature> features)
        {
            Copy(features);
            Delete(features);
        }

        /// <summary>
        /// 删除。
        /// </summary>
        /// <param name="features">图元集合。</param>
        public static void Delete(List<IShapeFeature> features)
        {
            foreach (var feature in features.Where(feature => feature.FeatureSet!=null))
            {
                feature.FeatureSet.ShapeFeatures.Remove(feature);
            }
        }

        /// <summary>
        /// 粘贴。
        /// </summary>
        /// <param name="shapeSet"></param>
        public static bool Paste(IFeatureSet shapeSet)
        {
            if (IsDirty)
            {
                //ShapesCommonHelper.ClearSelection(shapeSet);
                NewFeatures.Clear();
                foreach (var feature in CopiedGhosts.Select(ghost => (IShapeFeature)Restore(ghost)))
                {
                    NewFeatures.Add(feature);
                }
                foreach (var ghost in CopiedGhosts)
                {
                    RestoreRelation(ghost);
                }
                foreach (var ghost in CopiedGhosts)
                {
                    ResetNewObject(ghost);
                }
            }
            return NewFeatures.Count > 0;
        }

        /// <summary>
        /// 根据幻影对象恢复图元对象。
        /// </summary>
        /// <param name="ghost">幻影对象。</param>
        /// <returns>图元对象。</returns>
        private static DependencyObject Restore(GhostObject ghost)
        {
            if (ghost.SnapMode)
            {
                var newObject = ghost.ObserverHost.CreateInstance();

                ((IGhostHost)newObject).Observer.BeginRestore();

                foreach (var ghostProperty in ghost.ObserverHost.Observer.GhostProperties.Where(ghostProperty => ghostProperty.Type != GhostProperytType.Base))
                {
                    ClearCollection(newObject, ghostProperty.Property);
                }

                foreach (GhostRestore action in ghost.ChildRestores)
                {
                    var g = action.Ghost;
                    var newMemberObject = Restore(g);
                    if (newMemberObject != null && g.CollectionProperty != null)
                    {
                        RestoreCollection(newObject, g.CollectionProperty, newMemberObject);
                    }
                }
                
                Restore(newObject, ghost);

                ((IGhostHost)newObject).Observer.EndRestore();

                ghost.ObserverHost.Observer.NewObject = newObject;
                return newObject;
            }
            return null;
        }
        
        /// <summary>
        /// 根据幻影对象恢复图元对象。（将幻影对象保存的属性值恢复到图元对象中）
        /// </summary>
        /// <param name="newObject">图元对象。</param>
        /// <param name="ghost">幻影对象。</param>
        private static void Restore(DependencyObject newObject,GhostObject ghost)
        {
            if (newObject == null || ghost == null) return;
            var e = ghost.ChildProperties.GetEnumerator();
            while (e.MoveNext())
            {
                var kv = e.Current;
                if (kv.Value.OldValue != null && kv.Value.NewValue != null)
                {
                    newObject.SetValue(kv.Key, kv.Value.NewValue);
                }
            }
        }

        /// <summary>
        /// 清空集合成员。
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="collectionProperty"></param>
        private static void ClearCollection(DependencyObject owner, DependencyProperty collectionProperty)
        {
            if (owner == null) return;
            var colleciton = owner.GetValue(collectionProperty) as IOperateCollection;
            if (colleciton != null)
            {
                colleciton.Clear();
            }
        }

        /// <summary>
        /// 恢复集合。
        /// </summary>
        /// <param name="owner"></param>
        /// <param name="collectionProperty"></param>
        /// <param name="member"></param>
        private static void RestoreCollection(DependencyObject owner, DependencyProperty collectionProperty, DependencyObject member)
        {
            var colleciton = owner.GetValue(collectionProperty) as IOperateCollection;
            if (colleciton != null)
            {
                colleciton.Add(member);
            }
        }

        /// <summary>
        /// 恢复关系。
        /// </summary>
        /// <param name="ghost"></param>
        /// <returns></returns>
        private static DependencyObject RestoreRelation(GhostObject ghost)
        {
            var newObject = ghost.ObserverHost.Observer.NewObject;
            if (newObject != null)
            {
                ((IGhostHost) newObject).Observer.BeginRestore();
                foreach (GhostRestore action in ghost.ChildRestores)
                {
                    var g = action.Ghost;
                    if (g.SnapMode) continue;
                    var newMemberObject = RestoreRelation(g);
                    if (newMemberObject != null && g.CollectionProperty != null)
                    {
                        RestoreCollection(newObject, g.CollectionProperty, newMemberObject);
                    }
                }
                ((IGhostHost) newObject).Observer.EndRestore();
            }
            return newObject;
        }

        /// <summary>
        /// 重置新对象。
        /// </summary>
        /// <param name="ghost"></param>
        private static void ResetNewObject(GhostObject ghost)
        {
            ghost.ObserverHost.Observer.NewObject = null;
            foreach (GhostRestore action in ghost.ChildRestores)
            {
                ResetNewObject(action.Ghost);
            }
        }

        /// <summary>
        /// 克隆。
        /// </summary>
        /// <param name="shapeFeatures">被克隆的图元集合。</param>
        /// <returns>克隆得到的图元集合。</returns>
        public static List<IShapeFeature> Clone(List<IShapeFeature> shapeFeatures)
        {
            if (shapeFeatures != null && shapeFeatures.Count > 0)
            {
                var ghosts = shapeFeatures.Select(featue => ((IGhostHost) featue).Ghost).ToList();
                var newFeatures = ghosts.Select(ghost => (IShapeFeature) Restore(ghost)).ToList();
                foreach (var ghost in ghosts)
                {
                    RestoreRelation(ghost);
                }
                foreach (var ghost in ghosts)
                {
                    ResetNewObject(ghost);
                }
                return newFeatures;
            }
            return null;
        }

        /// <summary>
        /// 复制图元组。
        /// </summary>
        /// <param name="shapeSet"></param>
        /// <returns></returns>
        public static List<IShapeFeature> CreateTemplate(IFeatureSet shapeSet)
        {
            var features = new List<IShapeFeature>();
            if (shapeSet.Selection.Count <= 0) return null;
            features.AddRange(shapeSet.Selection.OfType<IShapeFeature>());
            return features.Count > 0 ? Clone(features) : null;
        }
    }
}
